﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DLM.Domain.Model;
using DLM.Domain.Repositories;
using DLM.Infrastructure.Domain;
using DLM.Infrastructure.Logging;
using DLM.Infrastructure.Payment;
using DLM.Infrastructure.UnitOfWork;
using DLM.Services.Interfaces;
using System.Xml;
using System.Text;
using DLM.Infrastructure.Authentication;

namespace DLM.Services.Implementations
{
    public class PaymentService : DLM.Services.Interfaces.IPaymentService
    {
        private IOrderRepository orderRepository;
        private IUserRepository userRepository;
        private IAccountRepositroy accountRepository;
        private IBonusRepository bonusRepository;
        private IBonusLogRepository bonusLogRepository;
        private IFormsAuthentication formAuth;
        private IUserService userService;
        private DLM.Infrastructure.Payment.IPaymentService aliPay;

        public PaymentService(IOrderRepository orderRepository, DLM.Infrastructure.Payment.IPaymentService aliPay,
            IUserRepository userRepository, IAccountRepositroy accountRepository, IBonusRepository bonusRepository,
            IUserService userService, IFormsAuthentication formAuth,IBonusLogRepository bonusLogRepository)
        {
            this.orderRepository = orderRepository;
            this.userRepository = userRepository;
            this.accountRepository = accountRepository;
            this.bonusRepository = bonusRepository;
            this.bonusLogRepository = bonusLogRepository;
            this.userService = userService;
            this.formAuth = formAuth;
            this.aliPay = aliPay;
        }

        public string PayForOrder(SortedDictionary<string, string> sParaTemp)
        {
            if (sParaTemp == null)
            {
                throw new ArgumentNullException("sParaTemp");
            }
            User user = this.userRepository.FindByName(HttpContext.Current.User.Identity.Name);
            if (user != null && HttpContext.Current.User.Identity.IsAuthenticated)
            {
                try
                {
                    Order order = new Order
                    {
                        OrderDate = DateTime.Now,
                        IsConfirmed = false,
                        BuyerEmail = "",
                        Body = sParaTemp["body"],
                        OrderNo = sParaTemp["out_trade_no"],
                        Price = decimal.Parse(sParaTemp["price"]),
                        Subject = sParaTemp["subject"],
                        TradeNo = string.Empty,
                        TradeStatus = "WAIT_BUYER_PAY",
                        UpdateDate = DateTime.Now,
                        UserID = user.UserID
                    };
                    sParaTemp.Add("logistics_fee", "0.00");
                    sParaTemp.Add("quantity", "1");
                    sParaTemp.Add("payment_type", "1");
                    sParaTemp.Add("logistics_payment", "SELLER_PAY");
                    sParaTemp.Add("logistics_type", "EXPRESS");
                    sParaTemp.Add("receive_address", "都来米交友电子在线充值");
                    sParaTemp.Add("receive_mobile", user.Phone);
                    sParaTemp.Add("receive_name", user.AccountName);
                    sParaTemp.Add("receive_phone", user.Phone);
                    sParaTemp.Add("receive_zip", "");
                    sParaTemp.Add("show_url", "http://www.doulaimeet.com/orders");

                    // Add order to database
                    this.orderRepository.Add(order);
                    // Send request to paypal
                    return this.aliPay.Create_partner_trade_by_buyer(sParaTemp);



                }
                catch (Exception ex)
                {
                    LoggingFactory.GetLogger().Error(ex.Message, ex);
                    throw;
                }


            }
            return null;

        }

        public string ConfirmForOrder(Order item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            //支付宝交易号，支付宝根据商户请求，创建订单生成的支付宝交易号。
            string trade_no = item.TradeNo;


            //物流公司名称，物流公司名称
            string logistics_name ="其他";


            //物流发货单号
            string invoice_no = item.OrderNo;


            //物流发货时的运输类型，三个值可选：POST（平邮）、EXPRESS（快递）、EMS（EMS）
            string transport_type = "EXPRESS";
            //建议与创建交易时选择的运输类型一致

            //把请求参数打包成数组
            SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
            sParaTemp.Add("trade_no", trade_no);
            sParaTemp.Add("logistics_name", logistics_name);
            sParaTemp.Add("invoice_no", invoice_no);
            sParaTemp.Add("transport_type", transport_type);

            //构造确认发货接口，无需修改
            Service ali = new Service();
            XmlDocument xmlDoc = ali.Send_goods_confirm_by_platform(sParaTemp);

            LoggingFactory.GetLogger().Log(xmlDoc.ToString());

            StringBuilder sbxml = new StringBuilder();
            string nodeIs_success = xmlDoc.SelectSingleNode("/alipay/is_success").InnerText;
            if (nodeIs_success != "T")//请求不成功的错误信息
            {
                sbxml.Append("错误：" + xmlDoc.SelectSingleNode("/alipay/error").InnerText);
                LoggingFactory.GetLogger().Log("错误：" + xmlDoc.SelectSingleNode("/alipay/error").InnerText);
            }
            else//请求成功的支付返回宝处理结果信息
            {
                try
                {
                    sbxml.Append(xmlDoc.SelectSingleNode("/alipay/response").InnerText);

                    LoggingFactory.GetLogger().Log("成功发货：" + sbxml.ToString());

                    Order currentOrder = this.orderRepository.FindByOrderNo(item.OrderNo);
                    //currentOrder.IsConfirmed = true;
                    currentOrder.UpdateDate = DateTime.Now;
                    currentOrder.TradeStatus = "WAIT_BUYER_CONFIRM_GOODS";
                    this.orderRepository.Save(currentOrder);

                    User user = this.userRepository.FindBy(item.UserID);
                    if (user != null)
                    {
                        Bonus currentBonus = this.bonusRepository.FindByUser(user.UserID);
                        currentBonus.Bonuses += item.Price;
                        currentBonus.UpdateDate = DateTime.Now;
                        this.bonusRepository.Save(currentBonus);

                        BonusLog log = new BonusLog
                        {
                            Bonus = item.Price,
                            CreateDate = DateTime.Now,
                            UserID = user.UserID,
                            Desc = "支付宝充值"
                        };
                        this.bonusLogRepository.Add(log);

                        LoggingFactory.GetLogger().Log("Set bonus " + item.Price + "=====" + currentBonus.Bonuses.Value);
                    }
                }
                catch (Exception ex)
                {

                    LoggingFactory.GetLogger().Error(ex.Message, ex);
                }
      
                                          
            }
            return sbxml.ToString();
            
        }

        public string SendGoods(Order item,Order currentOrder)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            //支付宝交易号，支付宝根据商户请求，创建订单生成的支付宝交易号。
            string trade_no = item.TradeNo;


            //物流公司名称，物流公司名称
            string logistics_name = "其他";


            //物流发货单号
            string invoice_no = item.OrderNo;


            //物流发货时的运输类型，三个值可选：POST（平邮）、EXPRESS（快递）、EMS（EMS）
            string transport_type = "EXPRESS";
            //建议与创建交易时选择的运输类型一致

            //把请求参数打包成数组
            SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
            sParaTemp.Add("trade_no", trade_no);
            sParaTemp.Add("logistics_name", logistics_name);
            sParaTemp.Add("invoice_no", invoice_no);
            sParaTemp.Add("transport_type", transport_type);

            //构造确认发货接口，无需修改
            Service ali = new Service();
            XmlDocument xmlDoc = ali.Send_goods_confirm_by_platform(sParaTemp);

            LoggingFactory.GetLogger().Log(xmlDoc.ToString());

            StringBuilder sbxml = new StringBuilder();
            string nodeIs_success = xmlDoc.SelectSingleNode("/alipay/is_success").InnerText;
            if (nodeIs_success != "T")//请求不成功的错误信息
            {
                sbxml.Append("错误：" + xmlDoc.SelectSingleNode("/alipay/error").InnerText);
                LoggingFactory.GetLogger().Log("错误：" + xmlDoc.SelectSingleNode("/alipay/error").InnerText);
            }
            else//请求成功的支付返回宝处理结果信息
            {
                try
                {
                    sbxml.Append(xmlDoc.SelectSingleNode("/alipay/response").InnerText);

                    LoggingFactory.GetLogger().Log("成功发货：" + sbxml.ToString());

                   
                    //currentOrder.IsConfirmed = true;
                    currentOrder.UpdateDate = DateTime.Now;
                    currentOrder.TradeStatus = "WAIT_BUYER_CONFIRM_GOODS";
                    this.orderRepository.Save(currentOrder);

                    User user = this.userRepository.FindBy(item.UserID);
                    if (user != null)
                    {
                        Bonus currentBonus = this.bonusRepository.FindByUser(user.UserID);
                        currentBonus.Bonuses += item.Price;
                        currentBonus.UpdateDate = DateTime.Now;
                        this.bonusRepository.Save(currentBonus);

                        BonusLog log = new BonusLog
                        {
                            Bonus = item.Price,
                            CreateDate = DateTime.Now,
                            UserID = user.UserID,
                            Desc = "支付宝充值"
                        };
                        this.bonusLogRepository.Add(log);

                        LoggingFactory.GetLogger().Log("Set bonus " + item.Price + "=====" + currentBonus.Bonuses.Value);
                    }
                }
                catch (Exception ex)
                {

                    LoggingFactory.GetLogger().Error(ex.Message, ex);
                }


            }
            return sbxml.ToString();
        }

        public bool ProcessNotify(SortedDictionary<string, string> sParaTemp)
        {
            bool result = false;
            LoggingFactory.GetLogger().Log("Receive notify from ali");
            if (sParaTemp.Count > 0)//判断是否有带返回参数
            {
                Notify aliNotify = new Notify();
                bool verifyResult = aliNotify.Verify(sParaTemp, HttpContext.Current.Request.Form["notify_id"], HttpContext.Current.Request.Form["sign"]);

                if (verifyResult)//验证成功
                {
                    //获取支付宝的通知返回参数，可参考技术文档中服务器异步通知参数列表
                    string trade_no = HttpContext.Current.Request.Form["trade_no"];         //支付宝交易号
                    string order_no = HttpContext.Current.Request.Form["out_trade_no"];     //获取订单号
                    string total_fee = HttpContext.Current.Request.Form["price"];           //获取总金额
                    string subject = HttpContext.Current.Request.Form["subject"];           //商品名称、订单名称
                    string body = HttpContext.Current.Request.Form["body"];                 //商品描述、订单备注、描述
                    string buyer_email = HttpContext.Current.Request.Form["buyer_email"];   //买家支付宝账号
                    string trade_status = HttpContext.Current.Request.Form["trade_status"]; //交易状态
                    string receive_name = HttpContext.Current.Request.QueryString["receive_name"];
                    Order currentOrder = this.orderRepository.FindByOrderNo(order_no);
                    if (currentOrder == null)
                    {
                        LoggingFactory.GetLogger().Error("Order is null in payment notify", null);
                        return false;
                    }
                    if (currentOrder.IsConfirmed)
                    {
                        result = true; 
                    }
                    LoggingFactory.GetLogger().Log("Receive notify from ali" + order_no + "" + trade_no + "" + trade_status);
                    if (HttpContext.Current.Request.Form["trade_status"] == "WAIT_BUYER_PAY")
                    {//该判断表示买家已在支付宝交易管理中产生了交易记录，但没有付款
                        currentOrder.TradeNo = trade_no;
                        currentOrder.TradeStatus = trade_status;

                        currentOrder.UpdateDate = DateTime.Now;
                        this.orderRepository.Save(currentOrder);
                        result =true;
                        //HttpContext.Current.Response.Write("success");  //请不要修改或删除
                    }
                    else if (HttpContext.Current.Request.Form["trade_status"] == "WAIT_SELLER_SEND_GOODS")
                    {//该判断示买家已在支付宝交易管理中产生了交易记录且付款成功，但卖家没有发货

                        LoggingFactory.GetLogger().Log("Current status" + HttpContext.Current.Request.Form["trade_status"].ToString());
                        LoggingFactory.GetLogger().Log("Current order status" + currentOrder.TradeStatus);
                        if (currentOrder.TradeStatus == "WAIT_BUYER_PAY")
                        {
                            try
                            {
                                LoggingFactory.GetLogger().Log("In");
                                currentOrder.TradeNo = trade_no;
                                currentOrder.TradeStatus = trade_status;
                                currentOrder.UpdateDate = DateTime.Now;
                                this.orderRepository.Save(currentOrder);
                                //User user = this.userRepository.FindByName(receive_name);
                                string content = SendGoods(new Order { OrderNo = order_no, TradeNo = trade_no, Price = decimal.Parse(total_fee), UserID = currentOrder.UserID },currentOrder);
                                // HttpContext.Current.Response.Write(content);
                                LoggingFactory.GetLogger().Log("Send goods" + trade_no);
                                result = true;
                            }
                            catch (Exception ex)
                            {

                                LoggingFactory.GetLogger().Error(ex.Message, ex);
                            }
                    
                        }
                       
                        //HttpContext.Current.Response.Write("success");  //请不要修改或删除
                    }
                    else if (HttpContext.Current.Request.Form["trade_status"] == "WAIT_BUYER_CONFIRM_GOODS")
                    {//该判断表示卖家已经发了货，但买家还没有做确认收货的操作


                        if (currentOrder.TradeStatus == "WAIT_SELLER_SEND_GOODS")
                        {
                            currentOrder.TradeNo = trade_no;
                            currentOrder.TradeStatus = trade_status;
                            currentOrder.UpdateDate = DateTime.Now;

                            //User user = this.userRepository.FindByName(receive_name);
                            //if (user != null)
                            //{
                            //    Bonus currentBonus = this.bonusRepository.FindByUser(user.UserID);
                            //    currentBonus.Bonuses += decimal.Parse(total_fee);
                            //    currentBonus.UpdateDate = DateTime.Now;
                            //    this.bonusRepository.Save(currentBonus);
                            //    LoggingFactory.GetLogger().Log("Set bonus " + total_fee + "=====" + currentBonus.Bonuses.Value);
                            //}
                           
                            this.orderRepository.Save(currentOrder);
                            LoggingFactory.GetLogger().Log("Save price " + order_no + "" + trade_no + "" + trade_status + "-" + total_fee);
                            result = true;
                        }
                      
                        //HttpContext.Current.Response.Write("success");  //请不要修改或删除
                    }
                    else if (HttpContext.Current.Request.Form["trade_status"] == "TRADE_FINISHED")
                    {//该判断表示买家已经确认收货，这笔交易完成

                        if (currentOrder.TradeStatus == "WAIT_BUYER_CONFIRM_GOODS")
                        {
                            currentOrder.TradeNo = trade_no;
                            currentOrder.TradeStatus = trade_status;
                            currentOrder.IsConfirmed = true;
                            currentOrder.UpdateDate = DateTime.Now;
                            this.orderRepository.Save(currentOrder);
                            LoggingFactory.GetLogger().Log("Finished order " + order_no + "" + trade_no + "" + trade_status + "-" + total_fee);

                            result = true;
                        }
                      
                        // HttpContext.Current.Response.Write("success");  //请不要修改或删除
                    }
                    else
                    {
                        result = true ;
                        //HttpContext.Current.Response.Write("success");  //其他状态判断。
                    }

                }
            }
            return result;
        }

        public void ProcessReturnUrl(SortedDictionary<string, string> sParaTemp)
        {
            if (sParaTemp == null)
            {
                throw new ArgumentNullException("sParaTemp");
            }
            if (sParaTemp.Count > 0)//判断是否有带返回参数
            {
                Notify aliNotify = new Notify();
                bool verifyResult = aliNotify.Verify(sParaTemp, HttpContext.Current.Request.QueryString["notify_id"], HttpContext.Current.Request.QueryString["sign"]);

                if (verifyResult)//验证成功
                {
                    //获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表
                    string trade_no = HttpContext.Current.Request.QueryString["trade_no"];              //支付宝交易号
                    string order_no = HttpContext.Current.Request.QueryString["out_trade_no"];	        //获取订单号
                    string total_fee = HttpContext.Current.Request.QueryString["price"];	            //获取总金额
                    string subject = HttpContext.Current.Request.QueryString["subject"];                //商品名称、订单名称
                    string body = HttpContext.Current.Request.QueryString["body"];                      //商品描述、订单备注、描述
                    string buyer_email = HttpContext.Current.Request.QueryString["buyer_email"];        //买家支付宝账号
                    string receive_name = HttpContext.Current.Request.QueryString["receive_name"];      //收货人姓名
                    string receive_address = HttpContext.Current.Request.QueryString["receive_address"];//收货人地址
                    string receive_zip = HttpContext.Current.Request.QueryString["receive_zip"];        //收货人邮编
                    string receive_phone = HttpContext.Current.Request.QueryString["receive_phone"];    //收货人电话
                    string receive_mobile = HttpContext.Current.Request.QueryString["receive_mobile"];  //收货人手机
                    string trade_status = HttpContext.Current.Request.QueryString["trade_status"];      //交易状态

                    LoggingFactory.GetLogger().Log("Receive return Current  status" + HttpContext.Current.Request.QueryString["trade_status"]);
                    
                    if (HttpContext.Current.Request.QueryString["trade_status"] == "WAIT_SELLER_SEND_GOODS")
                    {
                        //判断该笔订单是否在商户网站中已经做过处理（可参考“集成教程”中“3.4返回数据处理”）
                        //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                        //如果有做过处理，不执行商户的业务程序
                        Order currentOrder = this.orderRepository.FindByOrderNo(order_no);
                        LoggingFactory.GetLogger().Log("Receive return Current order status" + currentOrder.TradeStatus);
                        if (currentOrder.TradeStatus == "WAIT_BUYER_PAY")
                        {
                            currentOrder.TradeNo = trade_no;
                            currentOrder.TradeStatus = trade_status;
                            // currentOrder.IsConfirmed = true;

                            // Calculate bonus
                            //User user = this.userRepository.FindByName(receive_name);
                            //Bonus bonus = new Bonus
                            //{
                            //    Bonuses = decimal.Parse(total_fee),
                            //    CreateDate = DateTime.Now,
                            //    UserID = user.UserID

                            //};

                            this.orderRepository.Save(currentOrder);
                            //this.bonusRepository.Add(bonus);

                            if (!HttpContext.Current.User.Identity.IsAuthenticated)
                            {
                                Account currentAccount = this.accountRepository.FindByName(receive_name);
                                if (currentAccount != null)
                                {
                                    this.formAuth.SetAuthenticationToken(receive_name, "User");
                                }

                            }
                        }

                    }
                }
            }
        }


        public IEnumerable<Order> MyOrders(string account, int pageIndex, int pageSize)
        {
            if (account == null)
            {
                throw new ArgumentNullException("Account");
            }
            
       
            return this.orderRepository.FindByAccount(account, pageIndex, pageSize);
        }

        public IEnumerable<Order> Orders(int pageIndex, int pageSize)
        {
            return this.orderRepository.FindAll(pageIndex, pageSize);
        }

        public Order DetailOrder(int orderID)
        {
            return this.orderRepository.FindBy(orderID);
        }


        public Order DetailOrder(string orderNo)
        {
            if (string.IsNullOrEmpty(orderNo))
            {
                throw new ArgumentNullException("Order no");
            }
            return this.orderRepository.FindByOrderNo(orderNo);
        }
    }
}
